<template>
  <view class="container">
    <view class="tab flexBetween">
      <view class="tab-item flexCenter" @click="handleSwitch(item, index)" v-for="(item, index) in tabList" :key="index" :class="tabActive === item.value ? 'avtive' : ''">
        <view>{{ item.label }}</view>
        <view class="strip"></view>
      </view>
    </view>
    <view class="template">
      <template v-if="tabActive == 1">
        <view class="header flexBetween">
          <view class="left flexLeftCenter">
            <view class="tag" @click="paste">粘贴文本</view>
          </view>
          <view class="right flexLeftCenter" @click="$refs.popup.open()">
            <view class="text">选择模板</view>
            <uni-icons type="right" size="20" color="#999"></uni-icons>
          </view>
        </view>
        <view class="textarea">
          <uni-easyinput :maxlength="maxlength" type="textarea" v-model="value" placeholder="请输入或粘贴需要配音的文字"></uni-easyinput>
        </view>
        <view class="bottom flexBetween">
          <view class="left flexLeftCenter">
            <view class="tag" @click="clearText">清空文本</view>
          </view>
          <view class="right flexLeftCenter">
            <view class="text">{{ currentLength }}/{{ maxlength }}</view>
          </view>
        </view>
      </template>
      <teleport v-else>
        <view class="upload flexCenter">
          <view class="btn" @click="selectFile">上传txt文件</view>
        </view>
        <view class="files" v-if="fileName">
          <view class="file-item flexBetween">
            <view class="name">{{ fileName }}</view>
            <uni-icons type="closeempty" size="18" @click="delFile"></uni-icons>
          </view>
        </view>
      </teleport>
    </view>
    <view class="parameter">
      <view class="voice item flexBetween">
        <view class="label">配音员</view>
        <view class="value flexLeftCenter" @click="toVoiceActor">
          <view class="text">{{ voiceInfo.name }}</view>
          <uni-icons type="right" size="20" color="#999"></uni-icons>
        </view>
      </view>
      <view class="speechRate item flexBetween">
        <view class="label">语速</view>
        <!-- <picker @change="bindPickerChange" :value="index" :range="speechRateList" range-key="value"> -->
        <!-- <view class="value flexLeftCenter"> -->
        <view class="value">
          <slider :value="speechRate" @change="speechRateChange" show-value min="-500" max="500" />
          <!-- <view class="text">{{ speechRate }}</view>
            <uni-icons type="right" size="20" color="#999"></uni-icons> -->
        </view>
        <!-- </picker> -->
      </view>
      <view class="volume item flexBetween">
        <view class="label">音量</view>
        <view class="value">
          <slider :value="volume" @change="sliderChange" show-value />
        </view>
      </view>
    </view>

    <view class="footer">
      <view class="btn" @click="audition" v-if="!duration">试听配音</view>
      <view class="btn" @click="stopAudio" v-else>停止播放 {{ duration }}</view>
      <view class="btn" @click="exportDubbing">导出配音</view>
    </view>

    <uni-popup ref="popup" type="bottom" :safe-area="false">
      <view class="popup-content">
        <view class="popup-head flexBetween">
          <view class="cancel"></view>
          <view class="text">选择模板</view>
          <uni-icons type="closeempty" size="25" color="#999" @click="$refs.popup.close()"></uni-icons>
        </view>
        <scroll-view class="scroll-Y" scroll-y="true">
          <view class="list">
            <view class="item" @click="select(item)" v-for="(item, index) in template" :key="index"> {{ item.type }} {{ item.name }} </view>
          </view>
        </scroll-view>
      </view>
    </uni-popup>
    <uni-popup ref="popup2" type="bottom" :safe-area="false">
      <view class="popup-content">
        <view class="popup-head flexBetween">
          <view class="cancel"></view>
          <view class="text">选择配音员</view>
          <uni-icons type="closeempty" size="25" color="#999" @click="$refs.popup2.close()"></uni-icons>
        </view>
        <scroll-view class="scroll-Y" scroll-y="true">
          <view class="list list2">
            <view class="item" @click="selectStaff(item)" v-for="(item, index) in voiceList" :key="index">
              <view class="name">{{ item.name }}</view>
              <view class="type">{{ item.type }}</view>
            </view>
          </view>
        </scroll-view>
      </view>
    </uni-popup>
  </view>
</template>

<script>
import { getDubbingArtist, dubAudition, dubDeriveDub, uploadFile } from '@/api/common.js'
import subscribe from '@/utils/subscribe'
export default {
  data() {
    return {
      tabList: [
        {
          label: '粘贴文案配音',
          value: 1
        },
        {
          label: '上传文件配音',
          value: 2
        }
      ],
      tabActive: 1,
      linkUrl: '',
      value: '白发青丝一瞬间，年华老去向谁言。春风若有怜花意，可否许我再少年。',
      maxlength: 3000, // 最大字数
      template: [
        {
          type: '[励志诗歌]',
          name: '青云志',
          content: '无人扶我青云志，我自踏雪至山巅。若是命中无此运，亦可孤身登昆仑。'
        },
        { type: '[空白模板]', name: '空白', content: '' }
      ],
      // 配音员
      voiceList: [],
      voiceInfo: {
        name: '',
        type: '',
        voice: ''
      },
      // 语速
      speechRateList: [
        {
          value: '0.8'
        },
        {
          value: '1.0'
        },
        {
          value: '1.2'
        },
        {
          value: '1.5'
        },
        {
          value: '2.0'
        }
      ],
      index: 0,
      speechRate: 0,
      volume: 50,
      audioContext: null, // 音频上下文
      duration: 0, // 音频时间
      fileUrl: '', // 文件地址
      fileName: '' // 文件名称
    }
  },
  onLoad() {
    this.getDubbingArtist()
  },
  onUnload() {
    // 退出页面 停止播放
    if (this.audioContext) {
      this.audioContext.stop()
      this.audioContext = null
      this.duration = 0
    }
  },
  computed: {
    currentLength() {
      return this.value.length
    }
  },
  methods: {
    ...subscribe,
    delFile() {
      this.fileUrl = ''
      this.fileName = ''
    },
    // 选择文件
    selectFile() {
      let that = this
      wx.chooseMessageFile({
        count: 1, //默认100
        type: 'file',
        success: function (res) {
          let fileInfo = res.tempFiles[0]
          let pos = fileInfo.name.lastIndexOf('.')
          let lastName = fileInfo.name.substring(pos, fileInfo.name.length)
          if (lastName.toLowerCase() !== '.txt') {
            uni.showToast({
              icon: 'none',
              title: '请上传txt文件'
            })
            return
          }
          // that.fileUrl = res.tempFiles[0].path
          that.uploadFile(
            {
              filePath: fileInfo.path
            },
            fileInfo.name
          )
        }
      })
    },
    uploadFile(data, name) {
      uni.showLoading({
        title: '正在上传中...',
        mask: true
      })
      uploadFile(data)
        .then((res) => {
          uni.hideLoading()
          uni.showToast({
            title: '上传成功',
            icon: 'none'
          })
          this.fileUrl = res.data
          this.fileName = name
        })
        .catch((err) => {
          uni.hideLoading()
        })
    },
    // tab切换
    handleSwitch(item) {
      this.tabActive = item.value
    },
    renewInfo(item) {
      this.voiceInfo = item
    },
    toVoiceActor() {
      uni.navigateTo({
        url: '/pages/voiceActor/index'
      })
    },
    // 获取配音员
    getDubbingArtist() {
      getDubbingArtist().then((res) => {
        this.voiceList = res.data
        if (this.voiceList.length && this.voiceList.length > 0) {
          for (let i = 0; i < this.voiceList.length; i++) {
            if (this.voiceList[i].data && this.voiceList[i].data.length) {
              this.voiceInfo = this.voiceList[i].data[0]
              break
            }
          }
        }
      })
    },
    // 导出配音
    exportDubbing() {
      if (this.tabActive == 1) {
        if (!this.value) {
          return uni.showToast({
            icon: 'none',
            title: '请输入文本'
          })
        }
      } else {
        if (!this.fileUrl) {
          return uni.showToast({
            icon: 'none',
            title: '请上传txt文件'
          })
        }
      }
      uni.showLoading({
        title: '正在生成中...',
        mask: true
      })
      let data =
        this.tabActive == 1
          ? {
              text: this.value,
              voice: this.voiceInfo.voice,
              speechRate: this.speechRate,
              volume: this.volume
            }
          : {
              textFileUrl: this.fileUrl,
              voice: this.voiceInfo.voice,
              speechRate: this.speechRate,
              volume: this.volume
            }
      dubDeriveDub(data)
        .then((res) => {
          uni.hideLoading()
          uni.showToast({
            title: res.data,
            icon: 'none'
          })
          this.getSubscribeList(false)
        })
        .catch((err) => {
          uni.hideLoading()
        })
    },
    // 试听配音
    audition() {
      if (this.tabActive == 1) {
        if (!this.value) {
          return uni.showToast({
            icon: 'none',
            title: '请输入文本'
          })
        }
      } else {
        if (!this.fileUrl) {
          return uni.showToast({
            icon: 'none',
            title: '请上传txt文件'
          })
        }
      }
      let data =
        this.tabActive == 1
          ? {
              text: this.value,
              voice: this.voiceInfo.voice,
              speechRate: this.speechRate,
              volume: this.volume
            }
          : {
              textFileUrl: this.fileUrl,
              voice: this.voiceInfo.voice,
              speechRate: this.speechRate,
              volume: this.volume
            }
      uni.showLoading({
        title: '正在生成中...',
        mask: true
      })

      dubAudition(data)
        .then((res) => {
          uni.hideLoading()
          // 创建音频上下文
          this.audioContext = uni.createInnerAudioContext()
          // 设置音频源
          this.audioContext.src = res.data
          // 播放音频
          this.audioContext.play(() => {
            console.log('开始播放')
          })
          // 监听播放结束
          this.audioContext.onEnded(() => {
            this.duration = 0
          })
          // 监听播放进度更新
          this.audioContext.onTimeUpdate(() => {
            this.updateDuration()
          })
        })
        .catch((err) => {
          uni.hideLoading()
        })
    },
    // 停止播放
    stopAudio() {
      if (this.audioContext) {
        this.audioContext.stop()
        this.audioContext = null
        this.duration = 0
      }
    },
    // 更新播放时间
    updateDuration() {
      if (this.audioContext) {
        // console.log('当前播放时间', this.audioContext.currentTime)
        const duration = this.audioContext.duration - this.audioContext.currentTime
        if (duration) {
          this.duration = Math.round(duration) // 四舍五入
        }
      }
    },
    // 粘贴链接
    paste() {
      let that = this
      uni.getClipboardData({
        success: function (res) {
          that.value = res.data
        }
      })
    },
    // 清除文本
    clearText() {
      let that = this
      uni.showModal({
        title: '提示',
        content: '是否清除输入框?',
        success: function (res) {
          if (res.confirm) {
            that.value = ''
          } else if (res.cancel) {
            // console.log('用户点击取消')
          }
        }
      })
    },
    // 选择模板
    select(item) {
      this.value = item.content
      this.$refs.popup.close()
    },
    // 选择配音员
    selectStaff(item) {
      this.voiceInfo = item
      this.$refs.popup2.close()
    },
    bindPickerChange: function (e) {
      // console.log('picker发送选择改变，携带值为', e.detail.value)
      this.index = e.detail.value
      this.speechRate = this.speechRateList[this.index].value
    },
    // 音量change
    sliderChange(e) {
      this.volume = e.detail.value
    },
    // 语速change
    speechRateChange(e) {
      this.speechRate = e.detail.value
    }
  }
}
</script>

<style lang="scss" scoped>
.container {
  // padding: 20rpx;
  padding-bottom: calc(150rpx + 20rpx + env(safe-area-inset-bottom));
  .tab {
    height: 88rpx;
    background: #ffffff;
    padding: 0 83rpx;
    border-top: 1rpx solid #ebedf0;
    .tab-item {
      font-weight: 600;
      font-size: 28rpx;
      color: #222222;
      line-height: 42rpx;
      height: 100%;
      position: relative;
      flex-direction: column;
      .strip {
        width: 50%;
        height: 8rpx;
        background: #fe754f;
        border-radius: 20rpx;
        display: none;
      }
      &.avtive {
        .strip {
          display: block;
        }
      }
    }
  }
  .template {
    background: #fff;
    border-radius: 20rpx;
    padding: 20rpx;
    margin-top: 20rpx;
    .header {
      .left {
        .tag {
          padding: 5rpx 10rpx;
          color: #666;
          border: 1rpx solid #666;
          border-radius: 10rpx;
        }
        .tag + .tag {
          margin-left: 20rpx;
        }
      }
      .right {
        .text {
          color: #ff7200;
        }
      }
    }
    .textarea {
      margin-top: 20rpx;
      ::v-deep .uni-easyinput__content-textarea {
        height: 120px;
        min-height: 120px;
      }
    }
    .bottom {
      margin-top: 20rpx;
      .left {
        .tag {
          padding: 5rpx 10rpx;
          color: #666;
          border: 1rpx solid #666;
          border-radius: 10rpx;
        }
        .tag + .tag {
          margin-left: 20rpx;
        }
      }
      .right {
        .text {
          color: #999;
        }
      }
    }
    .upload {
      .btn {
        width: 200rpx;
        height: 60rpx;
        line-height: 60rpx;
        text-align: center;
        background: radial-gradient(0% 70% at 50% 50%, #ff5b24 0%, #bc0a0d 100%);
        border-radius: 33rpx;
        font-size: 28rpx;
        color: #ffffff;
      }
    }
    .files {
      margin-top: 20rpx;
      .file-item {
        .name {
          font-weight: bold;
        }
      }
    }
  }
  .parameter {
    background: #fff;
    border-radius: 10rpx;
    margin-top: 20rpx;
    .item {
      padding: 20rpx;
      .value {
        .text {
          color: #999;
        }
      }
    }
    .speechRate,
    .volume {
      .value {
        flex: 1;
        margin-left: 100rpx;
        ::v-deep slider {
          margin: 0;
        }
      }
    }
  }

  .popup-content {
    background: #fff;
    border-radius: 16rpx 16rpx 0 0;
    padding-bottom: env(safe-area-inset-bottom);
    .popup-head {
      padding: 24rpx 32rpx;
      border-bottom: 1rpx solid #ededee;
      .text {
        font-weight: 600;
        font-size: 30rpx;
        color: #17191c;
        line-height: 35rpx;
      }
    }
    .scroll-Y {
      height: 50vh;
    }
    .list {
      padding: 10rpx 20rpx;
      .item {
        font-size: 30rpx;
        color: #333;
        padding: 10rpx;
      }
      .item + .item {
        border-top: 1rpx solid #99999947;
      }
    }
    .list2 {
      .item {
        .name {
          font-weight: 600;
        }
        .type {
          font-size: 26rpx;
          color: #999;
          margin-top: 10rpx;
        }
      }
    }
  }

  .footer {
    position: fixed;
    bottom: 0;
    left: 0;
    width: 100%;
    height: calc(150rpx + env(safe-area-inset-bottom));
    display: flex;
    align-items: center;
    justify-content: center;
    padding-bottom: calc(env(safe-area-inset-bottom));
    background-color: #fff;
    border-radius: 40rpx 40rpx 0rpx 0rpx;
    z-index: 99;
    .btn {
      width: 335rpx;
      height: 90rpx;
      line-height: 90rpx;
      background: #f9e8e8;
      border-radius: 45rpx;
      text-align: center;
      font-weight: 500;
      font-size: 32rpx;
      color: #ca1a1d;
      margin-right: 20rpx;
    }
    .btn:last-child {
      margin-right: 0;
      background: radial-gradient(0% 70% at 50% 50%, #ff5b24 0%, #bc0a0d 100%);
      color: #fff;
    }
  }
}
</style>
